import re
from queue import Empty
from threading import Thread
from wcferry import Wcf, WxMsg
import pymysql  # 替换原先的 mysql.connector
import requests

# 初始化 Wcf 实例
wcf = Wcf()

# 数据库连接配置
db_config = {
    'host': 'localhost',  # 数据库主机地址
    'user': 'root',  # 数据库用户名
    'password': 'root',  # 数据库密码
    'database': 'wxbot',  # 数据库名称
}


# 使用 PyMySQL 连接数据库
def connect_db():
    try:
        connection = pymysql.connect(
            host=db_config['host'],
            user=db_config['user'],
            password=db_config['password'],
            database=db_config['database'],
            charset='utf8mb4',  # 建议使用 utf8mb4 以支持更多字符
            cursorclass=pymysql.cursors.DictCursor
        )
        print("数据库连接成功")
        return connection
    except Exception as e:
        print(f"连接数据库失败: {e}")
        return None


# 超级管理员检查
def is_super_admin(wxid):
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = "SELECT COUNT(*) FROM admin WHERE wxid = %s"
                cursor.execute(sql, (wxid,))
                result = cursor.fetchone()
                return result['COUNT(*)'] > 0
        except Exception as e:
            print(f"查询超级管理员时出错: {e}")
            return False
        finally:
            connection.close()
    else:
        print("无法连接到数据库，超级管理员检查失败")
        return False


# 配置获取
def get_config(name):
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = "SELECT value FROM config WHERE name = %s"
                cursor.execute(sql, (name,))
                result = cursor.fetchone()
                return result['value'] if result else None
        except Exception as e:
            print(f"查询配置时出错: {e}")
            return None
        finally:
            connection.close()
    else:
        print("无法连接到数据库，配置获取失败")
        return None


# ================
# 以下是拆分后的四个方法
# ================

# 添加群聊白名单
def add_room_whitelist(roomid):
    if not roomid:
        print("错误：roomid 为空，无法添加群聊白名单")
        return
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = "INSERT INTO allow (type, identifier) VALUES (%s, %s)"
                cursor.execute(sql, ('room', roomid))
            connection.commit()
            print("添加群聊白名单成功")
            wcf.send_text("添加群聊白名单成功", roomid)
        except Exception as e:
            print(f"添加群聊白名单时出错: {e}")
            # 可根据需求区分错误类型，这里统一提示
            wcf.send_text("该群已在白名单中或操作失败", roomid)
        finally:
            connection.close()
    else:
        print("无法连接到数据库，群聊白名单操作失败")
        wcf.send_text("无法连接到数据库，群聊白名单操作失败", roomid)


# 删除群聊白名单
def delete_room_whitelist(roomid):
    if not roomid:
        print("错误：roomid 为空，无法删除群聊白名单")
        return
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = "DELETE FROM allow WHERE type = %s AND identifier = %s"
                cursor.execute(sql, ('room', roomid))
            connection.commit()
            print("删除群聊白名单成功")
            wcf.send_text("删除群聊白名单成功", roomid)
        except Exception as e:
            print(f"删除群聊白名单时出错: {e}")

        finally:
            connection.close()
    else:
        print("无法连接到数据库，群聊白名单操作失败")
        wcf.send_text("无法连接到数据库，群聊白名单操作失败", roomid)


# 添加个人白名单
def add_user_whitelist(wxid):
    if not wxid:
        print("错误：wxid 为空，无法添加个人白名单")
        return
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = "INSERT INTO allow (type, identifier) VALUES (%s, %s)"
                cursor.execute(sql, ('user', wxid))
            connection.commit()
            print("添加个人白名单成功")
            wcf.send_text("添加个人白名单成功", wxid)
        except Exception as e:
            print(f"添加个人白名单时出错: {e}")
            wcf.send_text("该用户已在白名单中或操作失败", wxid)
        finally:
            connection.close()
    else:
        print("无法连接到数据库，个人白名单操作失败")
        wcf.send_text("无法连接到数据库，个人白名单操作失败", wxid)


# 删除个人白名单
def delete_user_whitelist(wxid):
    if not wxid:
        print("错误：wxid 为空，无法删除个人白名单")
        return
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = "DELETE FROM allow WHERE type = %s AND identifier = %s"
                cursor.execute(sql, ('user', wxid))
            connection.commit()
            print("删除个人白名单成功")
            wcf.send_text("删除个人白名单成功", wxid)
        except Exception as e:
            print(f"删除个人白名单时出错: {e}")
            wcf.send_text("个人白名单删除失败", wxid)
        finally:
            connection.close()
    else:
        print("无法连接到数据库，个人白名单操作失败")
        wcf.send_text("无法连接到数据库，个人白名单操作失败", wxid)


# 白名单检查
def is_allowed(sender, roomid):
    """
    判断用户或群聊是否在白名单内
    """
    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                sql = """
                    SELECT COUNT(*) as count FROM allow WHERE type = %s AND identifier = %s
                """
                if roomid and re.search(r'@chatroom$', roomid):  # 群聊
                    cursor.execute(sql, ('room', roomid))
                else:  # 私聊
                    cursor.execute(sql, ('user', sender))

                result = cursor.fetchone()
                return result['count'] > 0  # 只返回 True / False
        except Exception as e:
            print(f"查询白名单时出错: {e}")
            return False
        finally:
            connection.close()
    else:
        print("数据库连接失败，无法检查白名单")
        return False


# 将消息存入数据库
def save_msg_to_db(sender, roomid, content, gpt_msg=""):
    """
    仅将**白名单内的群聊或个人消息**存入数据库，
    并且不对 /gpt /帮助 /add /delete 等指令进行存储。
    """

    # 判断是否为指令，如果是则跳过存储
    skip_commands = ["/帮助", "/add", "/delete"]
    if any(content.startswith(cmd) for cmd in skip_commands):
        print(f"跳过指令消息存储: {content}")
        return
    # ========== 修改开始：去除 <msg>...</msg> 标签的内容 ==========
    content = re.sub(r'<msg>.*?</msg>', '', content, flags=re.S)
    gpt_msg = re.sub(r'<msg>.*?</msg>', '', gpt_msg, flags=re.S)
    # ========== 修改结束 ==========
    print(f"尝试保存消息: sender: {sender}, roomid: {roomid}, content: {content}, gpt_msg: {gpt_msg}")

    # 确保用户或群在白名单内才存储消息
    if not is_allowed(sender, roomid):
        print(f"消息未存入数据库: {sender} 或 {roomid} 不在白名单内")
        return

    connection = connect_db()
    if connection:
        try:
            with connection.cursor() as cursor:
                if roomid and re.search(r'@chatroom$', roomid):  # 群聊
                    sql = "INSERT INTO gp (roomid, msg, gpt_msg) VALUES (%s, %s, %s)"
                    cursor.execute(sql, (roomid, content, gpt_msg))
                else:  # 私信
                    sql = "INSERT INTO users (sender, msg, gpt_msg) VALUES (%s, %s, %s)"
                    cursor.execute(sql, (sender, content, gpt_msg))

            connection.commit()
            print("消息已存入数据库")
        except Exception as e:
            print(f"插入数据库时出错: {e}")
        finally:
            connection.close()
    else:
        print("数据库连接失败，消息未存入")


# 处理 GPT 请求（占位函数，替换为实际调用 GPT API 的逻辑）
def gpt_request(messages):
    """
    调用 Adam Chatbot Chat Completions 接口，对用户输入进行回复。
    现增加预处理：将传入的 messages 列表拼接为一个完整字符串，格式为：
      [请你模仿一个计算机专业的低调大学生zp，请你简单回答他的同学提问的问题]
      + "当前问题" + messages[0]
      + "历史交流信息" + (messages[1], messages[2], ...)
    """

    # 如果 messages 为空，直接返回
    if not messages:
        return "没有可用的用户消息"

    # --------------------------
    #  1. 对 messages 进行预处理
    # --------------------------
    # messages[0] 视为“当前问题”，messages[1:] 视为“历史交流信息”
    # 根据需求拼接字符串
    final_text = (
        " "
        + " " + messages[0]  # 当前问题
        + "  " + " ".join(messages[1:])  # 其余消息作为历史信息
    )

    # 打印最终拼接结果，调试可用
    print("预处理后拼接的完整消息:\n", final_text)

    # --------------------------
    #  2. 构造 Chat Completions 请求体
    # --------------------------
    # 这里只创建一个 user 消息，将上面的 final_text 作为内容。
    chat_messages = [
        {
            "role": "user",
            "content": final_text
        }
    ]

    payload = {
        "model": "gpt-4o-mini",
        "messages": chat_messages,
        # "temperature": 0.7,   # 示例温度，越高输出越发散
        # "max_tokens": 1024    # 示例值，可根据自身需求调整
    }

    # --------------------------
    #  3. 请求头 & 接口地址
    # --------------------------
    headers = {
        "Authorization": "sk-aXj4rDMhxr0WnQ6NE53bB74fFeE64f3d8dF6628871Ba64Ef",  # 请替换为你的实际 sk-Token
        "Content-Type": "application/json",
        "Accept": "application/json"
    }
    url = "https://api.adamchatbot.chat/v1/chat/completions"

    # --------------------------
    #  4. 发起请求并处理响应
    # --------------------------
    try:
        response = requests.post(url, headers=headers, json=payload, timeout=30)
        response.raise_for_status()  # 若响应状态码非 2xx，则抛出异常

        data = response.json()
        if "choices" in data and len(data["choices"]) > 0:
            return data["choices"][0]["message"]["content"]
        else:
            return "未从接口获取到有效的回答"

    except Exception as e:
        print(f"调用GPT接口出错: {e}")
        return "接口开发中(异常)"


def processMsg(msg: WxMsg):
    """
    根据消息内容决定如何处理：
      1. 处理超级管理员指令；
      2. 处理普通用户指令；
      3. 如果是普通消息，只有白名单内的用户或群聊才存入数据库。
    """
    print(f"收到消息: {msg.content}")  # 打印收到的消息内容

    # 清理消息内容
    msg_content = msg.content.strip()

    # 检查超级管理员身份
    if msg.sender == 'wxid_gwhmredzdf1w22' or is_super_admin(msg.sender):
        if msg_content.startswith("/add"):
            if re.search(r'@chatroom$', msg.roomid):  # 添加群聊白名单
                add_room_whitelist(msg.roomid)
            else:  # 添加个人白名单
                add_user_whitelist(msg.sender)

        elif msg_content.startswith("/delete"):
            if re.search(r'@chatroom$', msg.roomid):  # 删除群聊白名单
                delete_room_whitelist(msg.roomid)
            else:  # 删除个人白名单
                delete_user_whitelist(msg.sender)

    # 检查是否在白名单
    if not is_allowed(msg.sender, msg.roomid):
        print(f"用户 {msg.sender} 或群 {msg.roomid} 不在白名单内，消息未存储")
        return

    # 处理指令
    if msg_content.startswith("/"):
        if msg_content.startswith("/gpt"):
            save_msg_to_db(msg.sender, msg.roomid, msg_content)

            # 获取最近 8 条消息
            connection = connect_db()
            messages = []
            if connection:
                try:
                    with connection.cursor() as cursor:
                        sql = """
                            SELECT msg FROM {table}
                            WHERE {field} = %s 
                            ORDER BY id DESC 
                            LIMIT 5
                        """.format(
                            table="gp" if re.search(r'@chatroom$', msg.roomid) else "users",
                            field="roomid" if re.search(r'@chatroom$', msg.roomid) else "sender"
                        )
                        cursor.execute(sql, (msg.roomid if re.search(r'@chatroom$', msg.roomid) else msg.sender,))
                        messages = [row['msg'] for row in cursor.fetchall()]
                except Exception as e:
                    print(f"查询数据库时出错: {e}")
                finally:
                    connection.close()

            response = gpt_request(messages)

            # 回复群聊或个人
            wcf.send_text(response, msg.roomid if re.search(r'@chatroom$', msg.roomid) else msg.sender)
            save_msg_to_db(msg.sender, msg.roomid, response, gpt_msg=response)

        elif msg_content.startswith("/帮助"):
            help_message = "WxBot_ZP持续开发中\n[旺柴][强]author: ZP\n仓库地址https://gitee.com/yr_binary/WXBOT-ZP"
            wcf.send_text(help_message, msg.roomid if re.search(r'@chatroom$', msg.roomid) else msg.sender)

    else:
        save_msg_to_db(msg.sender, msg.roomid, msg_content)


# 启动消息监听
def enableReceivingMsg():
    def innerWcFerryProcessMsg():
        while wcf.is_receiving_msg():
            try:
                # 获取一条消息
                msg = wcf.get_msg()
                print("已收到消息:")
                processMsg(msg)
            except Empty:
                continue
            except Exception as e:
                print(f"错误: {e}")

    print("启动消息监听...")
    wcf.enable_receiving_msg()
    # 启动后台线程监听消息
    Thread(target=innerWcFerryProcessMsg, name="ListenMessageThread", daemon=True).start()


# 启动消息监听
enableReceivingMsg()

# 保持程序运行，以便持续监听消息
wcf.keep_running()
